package com.samphanie.ane.core.security.config;

import com.samphanie.ane.core.properties.AneCoreProperties;
import com.samphanie.ane.core.security.components.CustomAccessDecisionManager;
import com.samphanie.ane.core.security.components.CustomSecurityMetadataSource;
import com.samphanie.ane.core.security.filter.CustomSecurityFilter;
import com.samphanie.ane.core.service.CustomSecurityService;
import com.samphanie.ane.core.service.DefaultUserDetailsPasswordService;
import com.samphanie.ane.core.service.DefaultUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.UserDetailsPasswordService;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.*;
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: 认证相关的扩展点配置。配置在这里的bean，业务系统都可以通过声明同类型或同名的bean来覆盖安全模块默认的配置。
 * @Author ZSY
 * @createTime 2021/3/11 21:00
 */
@Configuration
public class AuthenticationBeanConfig {

    @Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
    String jwkSetUri;

    @Autowired(required = false)
    private CustomSecurityService customSecurityService;
    @Resource
    private AneCoreProperties aneCoreProperties;

    /**
     * 默认密码处理器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 默认编码算法的 Id
        String idForEncode = "bcrypt";
        // 多种密码编码共存
        Map<String, PasswordEncoder> encoders = new HashMap<>();
        encoders.put(idForEncode, new BCryptPasswordEncoder());
        encoders.put("noop", NoOpPasswordEncoder.getInstance());
        encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
        encoders.put("scrypt", new SCryptPasswordEncoder());
        encoders.put("sha256", new StandardPasswordEncoder());
        return new DelegatingPasswordEncoder(idForEncode, encoders);
    }

    /**
     * 默认认证器
     */
    @Bean
    @ConditionalOnMissingBean(UserDetailsService.class)
    public UserDetailsService userDetailsService() {
        return new DefaultUserDetailsService();
    }
    @Bean
    @ConditionalOnMissingBean(UserDetailsService.class)
    public UserDetailsPasswordService userDetailsPasswordService() {
        return new DefaultUserDetailsPasswordService();
    }

    @Bean
    public JwtDecoder jwtDecoder() {
        return NimbusJwtDecoder.withJwkSetUri(this.jwkSetUri).build();
    }

    @Bean
    @ConditionalOnBean(name = "customSecurityService")
    public CustomSecurityFilter customSecurityFilter() {
        return new CustomSecurityFilter(aneCoreProperties, customSecurityMetadataSource());
    }

    @Bean
    @ConditionalOnBean(name = "customSecurityService")
    public CustomAccessDecisionManager customAccessDecisionManager() {
        return new CustomAccessDecisionManager();
    }

    @Bean
    @ConditionalOnBean(name = "customSecurityService")
    public CustomSecurityMetadataSource customSecurityMetadataSource() {
        return new CustomSecurityMetadataSource(customSecurityService);
    }


}
